﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using AForge.Imaging;
using System.Drawing.Imaging;
using AForge.Vision.Motion;
using System.Windows.Forms;

namespace ImageProcessor {
    public class FrameDifference {
        /// <summary>
        /// threshold for the Frame Difference Detection
        /// </summary>
        private int threshold;

        /// <summary>
        /// Threshold for the Frame Difference Detection
        /// </summary>
        public int Threshold {
            get {
                return threshold;
            }
            set {
                if( value > 255 ) {
                    threshold = 255;
                } else if( value < 0 ) {
                    threshold = 0;
                } else
                    threshold = value;
            }
        }

        /// <summary>
        /// Default motion detector
        /// </summary>
        private CustomFrameDifferenceDetector detector = null;

        public CustomFrameDifferenceDetector Detector {
            get {
                return this.detector;
            }
            set {
                if( value is CustomFrameDifferenceDetector )
                    this.detector = value;
                else
                    detector = new CustomFrameDifferenceDetector(true, true);
            }
        }

        /// <summary>
        /// The first frame to where the next frame will be subtracted
        /// </summary>
        private UnmanagedImage baseFrame = null;

        /// <summary>
        /// Stores the error message occured, if any
        /// </summary>
        private string errorMessage = "";

        /// <summary>
        /// Error message created during the process
        /// </summary>
        public string ErrorMessage {
            get {
                return errorMessage;
            }
        }

        /// <summary>
        /// Constructor for FrameDifference Class
        /// </summary>
        /// <param name="detector">Frame Difference Detector Object</param>
        public FrameDifference( CustomFrameDifferenceDetector detector ) {
            this.detector = detector;
        }

        /// <summary>
        /// Constructor for FrameDifference Class
        /// </summary>
        public FrameDifference() {
            this.detector = new CustomFrameDifferenceDetector(true, true);
        }

        /// <summary>
        /// Sets the First Frame
        /// </summary>
        /// <param name="baseFrame">First Frame</param>
        public void SetBaseFrame( string baseImageFilePath ) {
            try {
                this.SetBaseFrame((Bitmap)Bitmap.FromFile(baseImageFilePath));
            } catch( Exception e ) {
                this.errorMessage = e.Message;
            }
            
        }
        /// <summary>
        /// Sets the First Frame
        /// </summary>
        /// <param name="baseFrame">First Frame</param>
        public void SetBaseFrame( Bitmap baseFrame ) {
            this.SetBaseFrame(UnmanagedImage.FromManagedImage(baseFrame));
        }

        /// <summary>
        /// Sets the First Frame
        /// </summary>
        /// <param name="baseFrame">First Frame</param>
        public void SetBaseFrame( BitmapData baseFrame ) {
            this.SetBaseFrame(UnmanagedImage.FromManagedImage(baseFrame));
        }

        /// <summary>
        /// Sets the First Frame
        /// </summary>
        /// <param name="baseFrame">First Frame</param>
        public void SetBaseFrame( UnmanagedImage baseFrame ) {
            this.baseFrame = baseFrame;
        }

        
        /// <summary>
        /// Processes the difference of the frames
        /// </summary>
        /// <param name="image">Second Frame</param>
        /// <returns>Frame Difference</returns>
        public Bitmap Apply( Bitmap image ) {
            try {
                detector.DifferenceThreshold = this.threshold;
                detector.ProcessFrame(this.baseFrame);
                detector.ProcessFrame(UnmanagedImage.FromManagedImage(image));
                Bitmap bmp = detector.MotionFrame.ToManagedImage();
                detector.Reset();
                return bmp;
            } catch( Exception e ) {
                this.errorMessage = e.Message;
                return null;
            }
        }

        /// <summary>
        /// Processes the difference of the frames
        /// </summary>
        /// <param name="image">Second Frame</param>
        /// <returns>Frame Difference</returns>
        public Bitmap Apply( string imagePath ) {
            try {
                return this.Apply((Bitmap)Bitmap.FromFile(imagePath));
            } catch( Exception e ) {
                this.errorMessage = e.Message;
                return null;
            }
        }

        public void Reset() {
            try {
                detector.Reset();
            } catch( Exception e ) {
                this.errorMessage = e.Message;
            }
        }

    }
}
